package sudoku.main;

import java.util.ArrayList;

public class Sudoku {

	private int sudokuSize;
	private int moves = 0;
	public static Square[][] sudoku;


	public Sudoku(int sudokuSize) {
		this.sudokuSize = sudokuSize;

		sudoku = new Square[sudokuSize][sudokuSize];
		for(int y = 0; y < sudokuSize; y++) {
			for(int x = 0; x < sudokuSize; x++) {
				sudoku[y][x] = new Square(sudokuSize, x, y);
			}
		}
	}

	public void setNumber(int number, int x, int y) {
		moves--;
		sudoku[y][x].setSure(number);
		calculateRow(number, y);
		calculateColumn(number, x);
		calculateSector(number, x, y);

	}

	public void calculateMoves() {
		moves = 0;
		for(int y = 0; y < sudokuSize; y++) {
			for(int x = 0; x < sudokuSize; x++) {
				if(sudoku[y][x].isSure()) {
					moves++;
				}
			}
		}
	}

	private void calculateRow(int number, int y) {
		for(int x = 0; x < sudokuSize; x++) {
			sudoku[y][x].removeChance(number);
		}
	}

	private void calculateColumn(int number, int x) {
		for(int y = 0; y < sudokuSize; y++) {
			sudoku[y][x].removeChance(number);
		}
	}

	private void calculateSector(int number, int x, int y) {
		if(x == 0 || x == 3 || x == 6) {
			if(y == 0 || y == 3 || y == 6) {
				for(int i = 0; i < 3; i++) {
					for(int j = 0; j < 3; j++) {
						sudoku[y+i][x+j].removeChance(number);
					}
				}

			}
			if(y == 1 || y == 4 || y == 7) {
				for(int i = 0; i < 3; i++) {
					for(int j = 0; j < 3; j++) {
						sudoku[y-1+i][x+j].removeChance(number);
					}
				}

			}
			if(y == 2 || y == 5 || y == 8) {
				for(int i = 0; i < 3; i++) {
					for(int j = 0; j < 3; j++) {
						sudoku[y-2+i][x+j].removeChance(number);
					}
				}
			}
		}
		if(x == 1 || x == 4 || x == 7) {
			if(y == 0 || y == 3 || y == 6) {
				for(int i = 0; i < 3; i++) {
					for(int j = 0; j < 3; j++) {
						sudoku[y+i][x-1+j].removeChance(number);
					}
				}
			}
			if(y == 1 || y == 4 || y == 7) {
				for(int i = 0; i < 3; i++) {
					for(int j = 0; j < 3; j++) {
						sudoku[y-1+i][x-1+j].removeChance(number);
					}
				}
			}
			if(y == 2 || y == 5 || y == 8) {
				for(int i = 0; i < 3; i++) {
					for(int j = 0; j < 3; j++) {
						sudoku[y-2+i][x-1+j].removeChance(number);
					}
				}
			}
		}
		if(x == 2 || x == 5 || x == 8) {
			if(y == 0 || y == 3 || y == 6) {
				for(int i = 0; i < 3; i++) {
					for(int j = 0; j < 3; j++) {
						sudoku[y+i][x-2+j].removeChance(number);
					}
				}
			}
			if(y == 1 || y == 4 || y == 7) {
				for(int i = 0; i < 3; i++) {
					for(int j = 0; j < 3; j++) {
						sudoku[y-1+i][x-2+j].removeChance(number);
					}
				}
			}
			if(y == 2 || y == 5 || y == 8) {
				for(int i = 0; i < 3; i++) {
					for(int j = 0; j < 3; j++) {
						sudoku[y-2+i][x-2+j].removeChance(number);
					}
				}
			}
		}
	}

	public void calculatePossibilities() {
		for(int y = 0; y<sudokuSize; y++) {
			for(int x = 0; x<sudokuSize; x++) {
				if(sudoku[y][x].isSure()) {
					int number = sudoku[y][x].getNumber();
					calculateRow(number, y);
					calculateColumn(number, x);
					calculateSector(number, x, y);
				}
			}
		}
	}

	private void resetSudoku() {
		sudoku = new Square[sudokuSize][sudokuSize];
		for(int y = 0; y < sudokuSize; y++) {
			for(int x = 0; x < sudokuSize; x++) {
				sudoku[y][x] = new Square(sudokuSize, x, y);
			}
		}
	}

	public void solve() {
		while(solveRow());
		while(solveColumn());
	}
	
	private boolean solveRow() {
		boolean solving = false;
		for(int y = 0; y < sudokuSize; y++) {
			int[] rowPossibilities = new int[sudokuSize+1];
			for(int q = 0; q <= sudokuSize; q++) {
				rowPossibilities[q] = 0;
			}
			
			for(int x = 0; x < sudokuSize; x++) {
				if(sudoku[y][x].getPossibilities().size() == 1) { //removing trivial possibilities
					setNumber(sudoku[y][x].getPossibilities().get(0), x, y);
					rowPossibilities[sudoku[y][x].getNumber()] = 0;
					solving = true;
				}
				for(int number: sudoku[y][x].getPossibilities()) {
					rowPossibilities[number] = rowPossibilities[number] + 1; 
				}
			}
			for(int number: rowPossibilities) {
				if(rowPossibilities[number] == 1) {
					for(int x = 0; x < sudokuSize; x++) {
						if(sudoku[y][x].getPossibilities().contains(number)) {
							setNumber(number, x, y);
							solving = true;
						}
					}
				}
			}
		}
		return solving;
	}
	
	private boolean solveColumn() {
		boolean solving = false;
		for(int x = 0; x < sudokuSize; x++) {
			int[] rowPossibilities = new int[sudokuSize+1];
			for(int q = 0; q <= sudokuSize; q++) {
				rowPossibilities[q] = 0;
			}
			
			for(int y = 0; y < sudokuSize; y++) {
				if(sudoku[y][x].getPossibilities().size() == 1) { //removing trivial possibilities
					setNumber(sudoku[y][x].getPossibilities().get(0), x, y);
					rowPossibilities[sudoku[y][x].getNumber()] = 0;
					solving = true;
				}
				for(int number: sudoku[y][x].getPossibilities()) {
					rowPossibilities[number] = rowPossibilities[number] + 1; 
				}
			}
			for(int number: rowPossibilities) {
				if(rowPossibilities[number] == 1) {
					for(int y = 0; y < sudokuSize; y++) {
						if(sudoku[y][x].getPossibilities().contains(number)) {
							setNumber(number, x, y);
							solving = true;
						}
					}
				}
			}
		}
		return solving;
	}





}
